package com.example.webgobang.component;

import com.example.webgobang.model.match.MatchRequest;
import com.example.webgobang.model.match.MatchResponse;
import com.example.webgobang.model.domin.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;

import static com.example.webgobang.common.Constants.SESSION_USER_KEY;

@Slf4j
@Component
public class MatchHandler extends TextWebSocketHandler {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Resource
    private OnlineUserManager userManager;

    @Resource
    private Matcher matcher;

    // WebSocket连接建立后
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        try {
            User user = (User) session.getAttributes().get(SESSION_USER_KEY);
            if(userManager.getSessionFromGameHall(user.getId()) != null
                    || userManager.getSessionFromGameRoom(user.getId()) != null) {
                // 多开拦截，新开的网页无法登录
                MatchResponse response = new MatchResponse();
                response.setOk(true);
                response.setMessage("repeatConnection");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                //session.close(); //连接正常断开，会触发afterConnectionClosed方法，需防止误删在线id
                return;
            }
            userManager.enterGameHall(user.getId(), session); //玩家上线
        } catch (Exception e) {
            log.error("用户未登录: " + e.getMessage());
            MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setReason("用户未登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response))); //对象->Json->WebSocket文本
        }
    }

    // 收到WebSocket数据后
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        User user = (User) session.getAttributes().get(SESSION_USER_KEY);
        String payload = message.getPayload();
        MatchRequest request = objectMapper.readValue(payload, MatchRequest.class); //Json->对象
        MatchResponse response = new MatchResponse();
        if("startMatch".equals(request.getMessage())) {
            matcher.add(user);
            response.setOk(true);
            response.setMessage("startMatch");
        } else if("stopMatch".equals(request.getMessage())) {
            matcher.remove(user);
            response.setOk(true);
            response.setMessage("stopMatch");
        } else {
            response.setOk(false);
            response.setMessage("未知请求");
        }
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
    }

    // 连接出现异常时
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        try {
            User user = (User) session.getAttributes().get(SESSION_USER_KEY);
            WebSocketSession tmpSession = userManager.getSessionFromGameHall(user.getId());
            if(tmpSession == session) {
                userManager.exitGameHall(user.getId()); //玩家下线
            }
            matcher.remove(user);
        } catch (Exception e) {
            log.error("[MatchWebSocketCallBacks-handleTransportError] 用户未登录: " + e.getMessage());
        }
    }

    // 连接正常断开后
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        try {
            User user = (User) session.getAttributes().get(SESSION_USER_KEY); //本次登录生成的会话
            WebSocketSession tmpSession = userManager.getSessionFromGameHall(user.getId()); //首次登录时记录的会话
            // 只有首次登录的会话会记录在userManager中，tmpSession与session相同，则本次登录就是首次登录，正常下线
            if(tmpSession == session) {
                userManager.exitGameHall(user.getId()); //玩家下线
            }
            matcher.remove(user);
        } catch (Exception e) {
            log.error("[MatchWebSocketCallBacks-afterConnectionClosed] 用户未登录: " + e.getMessage());
        }
    }
}
